﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using LuckyLoot.ServiceFacade.Implementation;
using LuckyLoot.ServiceFacade.Contracts;
using LuckyLoot.Presentation.BasePage;
using LuckyLoot.Domain.Aggregate;
using LuckyLoot.Common.Validation;
using LuckyLoot.Common;

namespace LuckyLoot.Presentation
{
    public partial class ApointmentPage : LuckyLootPage
    {
        private const string QueryStringApointmentID = "ApointmentID";

        private IApointmentService _apointmentService;
        public IApointmentService ApointmentService 
        {
            get
            {
                if (_apointmentService == null)
                    _apointmentService = new ApointmentService();

                return _apointmentService;
            }
        }

        public int ApointmentID
        {
            set
            {
                this.ViewState[QueryStringApointmentID] = value;
            }
            get
            {
                int viewStateTypedApointmentID;

                if (this.ViewState[QueryStringApointmentID] != null)
                {
                    if (Int32.TryParse(this.ViewState[QueryStringApointmentID].ToString(), out viewStateTypedApointmentID))
                        return viewStateTypedApointmentID;
                }

                return 0;
            }
        }

        public bool HasSelectedRecord
        {
            get
            {
                return ApointmentID > 0;
            }
        }

        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                this.BindArtists();
                this.BindCustomers();

                // TODO: [TELA DE AGENDAMENTO] Verificar como resolver a parte de adicionar fotos 
                if (!Page.IsPostBack)
                {
                    var apointmentIDString = HttpContext.Current.Request.QueryString[QueryStringApointmentID];
                    this.SelectRecord(apointmentIDString);
                }

                this.SetCommandsVisibility();

                this.SaveApointment.Click += new EventHandler(SaveApointmentClick);
                this.ConvertToTattooApointment.Click += new EventHandler(ConvertToTattooApointmentClick);

                this.BindGrid();
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        private void SetCommandsVisibility()
        {
            this.ConvertToTattooApointment.Visible = this.HasSelectedRecord;
        }


        private void SelectRecord(string id)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(id))
                {
                    int intID;
                    if (Int32.TryParse(id, out intID))
                        SelectRecord(intID);
                }
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        private void SelectRecord(int id)
        {
            try
            {
                ValidState.Requires<ArgumentException>(id > 0);
                var apointment = this.ApointmentService.GetApointment(id);

                SelectRecord(apointment);
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        private void SelectRecord(LuckyLoot.Domain.Aggregate.Apointment apointment)
        {
            try
            {
                this.apointmentTitle.Text = apointment.Title;
                this.apointmentDescription.Text = apointment.Description;
                this.apointmentCustomer.SelectedValue = apointment.Customer.Id.ToString();
                this.apointmentArtist.SelectedValue = apointment.Artist.Id.ToString();
                this.apointmentDate.Text = apointment.Date.ToString();
                this.apointmentReturnDate.Text = apointment.ReturnDate.HasValue ? apointment.ReturnDate.Value.ToString() : string.Empty;

                ApointmentID = apointment.Id;
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        private void ClearRecordSelection()
        {
            this.ApointmentID = 0;
            this.ClearFields();
        }

        private void ClearFields()
        {
            this.apointmentTitle.Text = string.Empty;
            this.apointmentDescription.Text = string.Empty;
            this.apointmentCustomer.SelectedIndex = 0;
            this.apointmentArtist.SelectedIndex = 0;
            this.apointmentDate.Text = string.Empty;
            this.apointmentReturnDate.Text = string.Empty; 
        }

        public void ConvertToTattooApointmentClick(object sender, EventArgs e)
        {
            try
            {
                if (HasSelectedRecord)
                {
                    var tattoo = this.ApointmentService.ConvertVisitToTattoo(ApointmentID);

                    Response.Redirect(string.Format("~/TattooApointment.aspx?{0}={1}", "TattooID", tattoo.Id.ToString()));
                }
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        public void SaveApointmentClick(object sender, EventArgs e)
        {
            try
            {
                DateTime? date = apointmentDate.Text.ToDateTime();
                if (!date.HasValue)
                    throw new ArgumentException("Não foi possível converter em uma Data o valor informado no campo Data.");

                DateTime? returnDate = this.apointmentReturnDate.Text.ToDateTime();

                int customer;
                if (!Int32.TryParse(apointmentCustomer.SelectedValue, out customer))
                    throw new ArgumentException("Não foi possível converter em um número o valor informado no campo Cliente.");

                int artist;
                if (!Int32.TryParse(apointmentArtist.SelectedValue, out artist))
                    throw new ArgumentException("Não foi possível converter em um número o valor informado no campo Artista.");

                Apointment apointment;
                if (this.HasSelectedRecord)
                    apointment = this.ApointmentService.UpdateApointment(ApointmentID, apointmentTitle.Text, apointmentDescription.Text, customer, artist, date.Value, returnDate);
                else
                    apointment = this.ApointmentService.ScheduleVisit(apointmentTitle.Text, apointmentDescription.Text, customer, artist, date.Value, returnDate);

                this.SelectRecord(apointment);
                MasterPage.ShowSuccessMessage("Agendamento de visita salvo com sucesso!");

                SetCommandsVisibility();

                this.BindGrid();
            }
            catch (Exception ex)
            {
                MasterPage.ShowErrorMessage(ex.Message);
            }
        }

        #region Binding

        private void BindArtists()
        {
            var userService = new UserService();
            var artists = userService.GetArtists();

            this.apointmentArtist.Items.Clear();

            foreach (var artist in artists)
            {
                this.apointmentArtist.Items.Add(new ListItem(artist.Name, artist.Id.ToString()));
            }
        }

        private void BindCustomers()
        {
            var customerService = new CustomerManagementService();
            var customers = customerService.GetAllCustomers();

            this.apointmentCustomer.Items.Clear();

            foreach (var customer in customers)
            {
                this.apointmentCustomer.Items.Add(new ListItem(customer.Name, customer.Id.ToString()));
            }
        }

        private void BindGrid()
        {
            var apointments = this.ApointmentService.GetAllApointments();

            if (apointments.Count() > 0)
            {
                this.apointmentsGrid.DataSource = apointments;
                this.apointmentsGrid.DataBind();
                this.apointmentsGrid.Visible = true;
                this.apointmentsLabel.Visible = true;
            }
        }

        #endregion
    }
}